﻿using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Input;
using Lhn.Ds.Core.CarDevice;
using Lhn.Ds.Core.Exceptions;
using Lhn.Ds.Core.Service;

namespace Lhn.Ds.Core.Controll
{
    public class ActivateBankCardModel : BaseModel
    {
        private CardInfoModel _cardInfoModel = new CardInfoModel();

        [Import] public CardService CardService { get; set; }
        [Import] public UsbCardService UsbCardService { get; set; }

        public CardInfoModel CardInfoModel
        {
            get => _cardInfoModel;
            set
            {
                if (_cardInfoModel == value) return;
                _cardInfoModel = value;
                OnPropertyChanged();
            }
        }

        public ICommand SaveCommand => new ReplayCommand(async _ =>
        {
            CardInfoModel cardInfoModel = new CardInfoModel()
            {
                CardState = CardState.Normal,
                Count = 0,
                Flags = 0,
                Balance = CardInfoModel.Balance,
                Total = 0,
                Type = CarTypeEnum.UseCard,
                LastSyncTime = new DateTime(),
                Numer = CardInfoModel.Numer,
                Phone = CardInfoModel.Phone,
            };
          
            UsbCardService.SelectCard();
            var serial = UsbCardService.ReadId();
            cardInfoModel.Code = UsbCardService.ReadStrId();
            var car = new CardService.Card
            {
                State = cardInfoModel.CardState,
                Balance = cardInfoModel.Balance,
                CardNumber = cardInfoModel.Numer,
                TotalConsumption = (int) cardInfoModel.Total,
                SynchronisedTime = cardInfoModel.LastSyncTime,
                CardType = cardInfoModel.Type,
                Code = cardInfoModel.Code,
                PhoneNum = cardInfoModel.Phone,
            };

            var remoteCar = await CardService.GetCard(car.Code);
            if (remoteCar != null) throw new CardNotBankException();
            try
            {
                if (UsbCardService.IsSytechCard())
                {
                    var info = UsbCardService.ReadCard();
                    if (info.CardState != CardState.Bank)
                        throw new CardNotBankException();
                    UsbCardService.WriteCard(cardInfoModel);
                }
                else
                {
                    UsbCardService.SetSytechPassword(serial);
                    UsbCardService.WriteCard(cardInfoModel);
                }

                await CardService.SaveCard(car);
                UsbCardService.Beep();
                DsContext.InstanceData.SnackbarMessageQueue.Enqueue("开卡成功");
                DispatchUI(() =>
                {
                    CardInfoModel.Numer = "";
                    CardInfoModel.Phone = "";
                    CardInfoModel.Balance = 0;
                });
            }
            catch (System.Exception e)
            {
                var rt = await CardService.GetCard(car.Code);
                if (rt != null)
                    await CardService.DeleteCard(rt.Id);
                if (e is SytechException)
                {
                    DsContext.InstanceData.ProccessException(e);
                }
                else
                {
                    DsContext.InstanceData.ProccessException(new SysException(e));
                }
            }
        }, () =>
        {
            try
            {
                var carNo = UsbCardService.ParseCarNoFromString(CardInfoModel.Numer);
                return true;
            }
            catch (Exception e)
            {
                //DsContext.InstanceData.ProccessException(e);
            }

            return false;
        });

        public ICommand ResetCommand => new ReplayCommand(_ =>
        {
            CardInfoModel.Phone = "";
            CardInfoModel.Numer = "";
            CardInfoModel.Balance = 0;
        });
    }

    public class CardNotBankException : CardException
    {
        public CardNotBankException(string message = "这不是一张空卡") : base(message)
        {
        }
    }
}